home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / Src / Ch10 / Julia.frm < prev    next >
Text File  |  1999-06-09  |  20KB  |  723 lines

  1. VERSION 5.00
  2. Object = "{F9043C88-F6F2-101A-A3C9-08002B2F49FB}#1.2#0"; "COMDLG32.OCX"
  3. Begin VB.Form frmJulia 
  4.    Caption         =   "Julia"
  5.    ClientHeight    =   3810
  6.    ClientLeft      =   2370
  7.    ClientTop       =   1320
  8.    ClientWidth     =   3810
  9.    LinkTopic       =   "Form1"
  10.    PaletteMode     =   1  'UseZOrder
  11.    ScaleHeight     =   254
  12.    ScaleMode       =   3  'Pixel
  13.    ScaleWidth      =   254
  14.    Begin MSComDlg.CommonDialog dlgFile 
  15.       Left            =   120
  16.       Top             =   120
  17.       _ExtentX        =   847
  18.       _ExtentY        =   847
  19.       _Version        =   393216
  20.    End
  21.    Begin VB.PictureBox picCanvas 
  22.       AutoRedraw      =   -1  'True
  23.       BackColor       =   &H00000000&
  24.       Height          =   3810
  25.       Left            =   0
  26.       MousePointer    =   2  'Cross
  27.       ScaleHeight     =   250
  28.       ScaleMode       =   3  'Pixel
  29.       ScaleWidth      =   250
  30.       TabIndex        =   0
  31.       Top             =   0
  32.       Width           =   3810
  33.    End
  34.    Begin VB.Menu mnuFile 
  35.       Caption         =   "&File"
  36.       Begin VB.Menu mnuFileSaveAs 
  37.          Caption         =   "&Save As..."
  38.          Shortcut        =   ^A
  39.       End
  40.    End
  41.    Begin VB.Menu mnuScaleMnu 
  42.       Caption         =   "&Scale"
  43.       Begin VB.Menu mnuScale 
  44.          Caption         =   "x&2"
  45.          Index           =   2
  46.       End
  47.       Begin VB.Menu mnuScale 
  48.          Caption         =   "x&4"
  49.          Index           =   4
  50.       End
  51.       Begin VB.Menu mnuScale 
  52.          Caption         =   "x&8"
  53.          Index           =   8
  54.       End
  55.       Begin VB.Menu mnuScaleFull 
  56.          Caption         =   "&Full Scale"
  57.       End
  58.    End
  59.    Begin VB.Menu mnuOpt 
  60.       Caption         =   "&Options"
  61.       Begin VB.Menu mnuOptOptions 
  62.          Caption         =   "&Set Options"
  63.       End
  64.       Begin VB.Menu mnuOptSep 
  65.          Caption         =   "-"
  66.       End
  67.       Begin VB.Menu mnuOptMandelbrotSet 
  68.          Caption         =   "&Mandelbrot Set"
  69.          Checked         =   -1  'True
  70.          Shortcut        =   ^M
  71.       End
  72.       Begin VB.Menu mnuOptJuliaSet 
  73.          Caption         =   "&Julia Set"
  74.          Shortcut        =   ^J
  75.       End
  76.    End
  77.    Begin VB.Menu mnuMovie 
  78.       Caption         =   "&Movie"
  79.       Begin VB.Menu mnuMovieCreate 
  80.          Caption         =   "&Create Movie..."
  81.       End
  82.    End
  83. End
  84. Attribute VB_Name = "frmJulia"
  85. Attribute VB_GlobalNameSpace = False
  86. Attribute VB_Creatable = False
  87. Attribute VB_PredeclaredId = True
  88. Attribute VB_Exposed = False
  89. Option Explicit
  90.  
  91. Private m_DrawingBox As Boolean
  92. Private m_StartX As Single
  93. Private m_StartY As Single
  94. Private m_CurX As Single
  95. Private m_CurY As Single
  96.  
  97. Private m_Xmin As Single
  98. Private m_Xmax As Single
  99. Private m_Ymin As Single
  100. Private m_Ymax As Single
  101.  
  102. Public MaxMandelbrotIterations As Integer
  103. Public MaxJuliaIterations As Integer
  104.  
  105. Public numcolors As Integer
  106. Private m_Colors() As Long
  107.  
  108. Private Const MIN_X = -2.2
  109. Private Const MAX_X = 1
  110. Private Const MIN_Y = -1.2
  111. Private Const MAX_Y = 1.2
  112.  
  113. ' 0 = Mandelbrot set
  114. ' 1 = Julia set
  115. Private Enum FractalTypes
  116.     fractal_Mandelbrot = 0
  117.     fractal_Julia = 1
  118. End Enum
  119. Private m_SelectedFractal As FractalTypes
  120.  
  121. Private m_Mandelbrot_Xmin As Single
  122. Private m_Mandelbrot_Xmax As Single
  123. Private m_Mandelbrot_Ymin As Single
  124. Private m_Mandelbrot_Ymax As Single
  125. Private m_Julia_ReaC As Single
  126. Private m_Julia_ImaC As Single
  127.  
  128. ' Draw the appropriate fractal.
  129. Private Sub DrawFractal()
  130.     If m_SelectedFractal = fractal_Mandelbrot Then
  131.         DrawMandelbrot
  132.     Else
  133.         DrawJulia
  134.     End If
  135. End Sub
  136.  
  137.  
  138. ' Return this color's value.
  139. Property Get color(ByVal Index As Integer) As Long
  140.     color = m_Colors(Index)
  141. End Property
  142.  
  143. ' Add this color to the list.
  144. Public Sub AddColor(ByVal new_color As Long)
  145.     numcolors = numcolors + 1
  146.     ReDim Preserve m_Colors(1 To numcolors)
  147.     m_Colors(numcolors) = new_color
  148. End Sub
  149. ' Adjust the aspect ratio of the selected
  150. ' coordinates so they fit the window properly.
  151. Private Sub AdjustAspect()
  152. Dim want_aspect As Single
  153. Dim picCanvas_aspect As Single
  154. Dim hgt As Single
  155. Dim wid As Single
  156. Dim mid As Single
  157.  
  158.     want_aspect = (m_Ymax - m_Ymin) / (m_Xmax - m_Xmin)
  159.     picCanvas_aspect = picCanvas.ScaleHeight / picCanvas.ScaleWidth
  160.     If want_aspect > picCanvas_aspect Then
  161.         ' The selected area is too tall and thin.
  162.         ' Make it wider.
  163.         wid = (m_Ymax - m_Ymin) / picCanvas_aspect
  164.         mid = (m_Xmin + m_Xmax) / 2
  165.         m_Xmin = mid - wid / 2
  166.         m_Xmax = mid + wid / 2
  167.     Else
  168.         ' The selected area is too short and wide.
  169.         ' Make it taller.
  170.         hgt = (m_Xmax - m_Xmin) * picCanvas_aspect
  171.         mid = (m_Ymin + m_Ymax) / 2
  172.         m_Ymin = mid - hgt / 2
  173.         m_Ymax = mid + hgt / 2
  174.     End If
  175. End Sub
  176.  
  177.  
  178. ' Draw the Mandelbrot set.
  179. Private Sub DrawMandelbrot()
  180. ' Work until the magnitude squared > 4.
  181. Const MAX_MAG_SQUARED = 4
  182.  
  183. Dim pixels() As RGBTriplet
  184. Dim bits_per_pixel As Integer
  185. Dim wid As Long
  186. Dim hgt As Long
  187. Dim clr As Integer
  188. Dim color As Long
  189. Dim i As Integer
  190. Dim j As Integer
  191. Dim ReaC As Double
  192. Dim ImaC As Double
  193. Dim dReaC As Double
  194. Dim dImaC As Double
  195. Dim ReaZ As Double
  196. Dim ImaZ As Double
  197. Dim ReaZ2 As Double
  198. Dim ImaZ2 As Double
  199. Dim r As Integer
  200. Dim b As Integer
  201. Dim g As Integer
  202.  
  203.     picCanvas.Line (0, 0)-(picCanvas.ScaleWidth, picCanvas.ScaleHeight), vbBlack, BF
  204.     DoEvents
  205.  
  206.     ' Get the image's pixels.
  207.     GetBitmapPixels picCanvas, pixels, bits_per_pixel
  208.  
  209.     ' Adjust the coordinate bounds to fit picCanvas.
  210.     AdjustAspect
  211.  
  212.     ' dReaC is the change in the real part
  213.     ' (X value) for C. dImaC is the change in the
  214.     ' imaginary part (Y value).
  215.     wid = picCanvas.ScaleWidth
  216.     hgt = picCanvas.ScaleHeight
  217.     dReaC = (m_Xmax - m_Xmin) / (wid - 1)
  218.     dImaC = (m_Ymax - m_Ymin) / (hgt - 1)
  219.  
  220.     ' Calculate the values.
  221.     ReaC = m_Xmin
  222.     For i = 0 To wid - 1
  223.         ImaC = m_Ymin
  224.         For j = 0 To hgt - 1
  225.             ReaZ = 0
  226.             ImaZ = 0
  227.             ReaZ2 = 0
  228.             ImaZ2 = 0
  229.             clr = 1
  230.             Do While clr < MaxMandelbrotIterations And _
  231.                     ReaZ2 + ImaZ2 < MAX_MAG_SQUARED
  232.                 ' Calculate Z(clr).
  233.                 ReaZ2 = ReaZ * ReaZ
  234.                 ImaZ2 = ImaZ * ImaZ
  235.                 ImaZ = 2 * ImaZ * ReaZ + ImaC
  236.                 ReaZ = ReaZ2 - ImaZ2 + ReaC
  237.                 clr = clr + 1
  238.             Loop
  239.  
  240.             color = m_Colors(1 + clr Mod numcolors)
  241.             With pixels(i, j)
  242.                 .rgbRed = color And &HFF&
  243.                 .rgbGreen = (color And &HFF00&) \ &H100&
  244.                 .rgbBlue = (color And &HFF0000) \ &H10000
  245.             End With
  246.  
  247.             ImaC = ImaC + dImaC
  248.         Next j
  249.         ReaC = ReaC + dReaC
  250.  
  251.         ' Let the user know we're not dead.
  252.         If i Mod 10 = 0 Then
  253.             picCanvas.Line (0, 0)-(wid, i), vbWhite, BF
  254.             picCanvas.Refresh
  255.         End If
  256.     Next i
  257.  
  258.     ' Update the image.
  259.     SetBitmapPixels picCanvas, bits_per_pixel, pixels
  260.     picCanvas.Refresh
  261.     picCanvas.Picture = picCanvas.Image
  262.  
  263.     Caption = "Julia (" & Format$(m_Xmin) & ", " & _
  264.         Format$(m_Ymin) & ")-(" & _
  265.         Format$(m_Xmax) & ", " & _
  266.         Format$(m_Ymax) & ")"
  267. End Sub
  268. ' Draw the Mandelbrot set.
  269. Private Sub DrawJulia()
  270. ' Work until the magnitude squared > 4.
  271. Const MAX_MAG_SQUARED = 4
  272.  
  273. Dim pixels() As RGBTriplet
  274. Dim bits_per_pixel As Integer
  275. Dim wid As Long
  276. Dim hgt As Long
  277. Dim clr As Long
  278. Dim color As Long
  279. Dim i As Integer
  280. Dim j As Integer
  281. Dim dReaZ0 As Double
  282. Dim dImaZ0 As Double
  283. Dim ReaZ0 As Double
  284. Dim ImaZ0 As Double
  285. Dim ReaZ As Double
  286. Dim ImaZ As Double
  287. Dim ReaZ2 As Double
  288. Dim ImaZ2 As Double
  289. Dim r As Integer
  290. Dim b As Integer
  291. Dim g As Integer
  292.  
  293.     picCanvas.Line (0, 0)-(picCanvas.ScaleWidth, picCanvas.ScaleHeight), vbBlack, BF
  294.     DoEvents
  295.  
  296.     ' Get the image's pixels.
  297.     GetBitmapPixels picCanvas, pixels, bits_per_pixel
  298.  
  299.     ' Adjust the coordinate bounds to fit picCanvas.
  300.     AdjustAspect
  301.  
  302.     ' dReaZ0 is the change in the real part
  303.     ' (X value) for Z0. dImaZ0 is the change in the
  304.     ' imaginary part (Y value).
  305.     wid = picCanvas.ScaleWidth
  306.     hgt = picCanvas.ScaleHeight
  307.     dReaZ0 = (m_Xmax - m_Xmin) / (wid - 1)
  308.     dImaZ0 = (m_Ymax - m_Ymin) / (hgt - 1)
  309.  
  310.     ' Calculate the values.
  311.     ReaZ0 = m_Xmin
  312.     For i = 0 To wid - 1
  313.         ImaZ0 = m_Ymin
  314.         For j = 0 To hgt - 1
  315.             ReaZ = ReaZ0
  316.             ImaZ = ImaZ0
  317.             ReaZ2 = ReaZ * ReaZ
  318.             ImaZ2 = ImaZ * ImaZ
  319.             clr = 1
  320.             Do While clr < MaxJuliaIterations And _
  321.                     ReaZ2 + ImaZ2 < MAX_MAG_SQUARED
  322.                 ' Calculate Z(clr).
  323.                 ReaZ2 = ReaZ * ReaZ
  324.                 ImaZ2 = ImaZ * ImaZ
  325.                 ImaZ = 2 * ImaZ * ReaZ + m_Julia_ImaC
  326.                 ReaZ = ReaZ2 - ImaZ2 + m_Julia_ReaC
  327.                 clr = clr + 1
  328.             Loop
  329.  
  330.             If clr >= MaxJuliaIterations Then
  331.                 ' Use a non-background color.
  332.                 color = m_Colors(((ReaZ2 + ImaZ2) * _
  333.                     (numcolors - 1)) Mod _
  334.                     (numcolors - 1) + 1)
  335.             Else
  336.                 ' Use the background color.
  337.                 color = m_Colors(1)
  338.             End If
  339.             With pixels(i, j)
  340.                 .rgbRed = color And &HFF&
  341.                 .rgbGreen = (color And &HFF00&) \ &H100&
  342.                 .rgbBlue = (color And &HFF0000) \ &H10000
  343.             End With
  344.  
  345.             ImaZ0 = ImaZ0 + dImaZ0
  346.         Next j
  347.         ReaZ0 = ReaZ0 + dReaZ0
  348.  
  349.         ' Let the user know we're not dead.
  350.         If i Mod 10 = 0 Then
  351.             picCanvas.Line (0, 0)-(wid, i), vbWhite, BF
  352.             picCanvas.Refresh
  353.         End If
  354.     Next i
  355.  
  356.     ' Update the image.
  357.     SetBitmapPixels picCanvas, bits_per_pixel, pixels
  358.     picCanvas.Refresh
  359.     picCanvas.Picture = picCanvas.Image
  360.  
  361.     Caption = "Julia (" & Format$(m_Xmin) & ", " & _
  362.         Format$(m_Ymin) & ")-(" & _
  363.         Format$(m_Xmax) & ", " & _
  364.         Format$(m_Ymax) & ")"
  365. End Sub
  366.  
  367. ' Reset the number of colors to 0.
  368. Public Sub ResetColors()
  369.     numcolors = 0
  370.     Erase m_Colors
  371. End Sub
  372.  
  373. ' Display the Julia set.
  374. Private Sub mnuOptJuliaSet_Click()
  375.     If m_SelectedFractal = fractal_Julia Then Exit Sub
  376.  
  377.     ' Save the current Mandelbrot position.
  378.     m_Mandelbrot_Xmin = m_Xmin
  379.     m_Mandelbrot_Xmax = m_Xmax
  380.     m_Mandelbrot_Ymin = m_Ymin
  381.     m_Mandelbrot_Ymax = m_Ymax
  382.  
  383.     ' Use the center as C for the Julia set.
  384.     m_Julia_ReaC = (m_Xmin + m_Xmax) / 2
  385.     m_Julia_ImaC = (m_Ymin + m_Ymax) / 2
  386.  
  387.     mnuOptJuliaSet.Checked = True
  388.     mnuOptMandelbrotSet.Checked = False
  389.     m_SelectedFractal = fractal_Julia
  390.  
  391.     ' Zoom out.
  392.     mnuScaleFull_Click
  393. End Sub
  394. ' Select this kind of fractal.
  395. Private Sub mnuOptMandelbrotSet_Click()
  396.     If m_SelectedFractal = fractal_Mandelbrot Then Exit Sub
  397.  
  398.     ' Restore the Mandelbrot position.
  399.     m_Xmin = m_Mandelbrot_Xmin
  400.     m_Xmax = m_Mandelbrot_Xmax
  401.     m_Ymin = m_Mandelbrot_Ymin
  402.     m_Ymax = m_Mandelbrot_Ymax
  403.  
  404.     mnuOptJuliaSet.Checked = False
  405.     mnuOptMandelbrotSet.Checked = True
  406.     m_SelectedFractal = fractal_Mandelbrot
  407.  
  408.     ' Redraw.
  409.     Screen.MousePointer = vbHourglass
  410.     DrawFractal
  411.     Screen.MousePointer = vbDefault
  412. End Sub
  413.  
  414. ' Start a rubberband box to select a zoom area.
  415. Private Sub picCanvas_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
  416.     m_DrawingBox = True
  417.     m_StartX = X
  418.     m_StartY = Y
  419.     m_CurX = X
  420.     m_CurY = Y
  421.     picCanvas.DrawMode = vbInvert
  422.     picCanvas.Line (m_StartX, m_StartY)-(m_CurX, m_CurY), , B
  423. End Sub
  424.  
  425.  
  426. ' Continue the zoom area rubberband box.
  427. Private Sub picCanvas_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
  428.     If Not m_DrawingBox Then Exit Sub
  429.     picCanvas.Line (m_StartX, m_StartY)-(m_CurX, m_CurY), , B
  430.     m_CurX = X
  431.     m_CurY = Y
  432.     picCanvas.Line (m_StartX, m_StartY)-(m_CurX, m_CurY), , B
  433. End Sub
  434.  
  435.  
  436. ' Zoom in on the selected area.
  437. Private Sub picCanvas_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
  438. Dim x1 As Single
  439. Dim x2 As Single
  440. Dim y1 As Single
  441. Dim y2 As Single
  442. Dim factor As Single
  443.  
  444.     If Not m_DrawingBox Then Exit Sub
  445.     m_DrawingBox = False
  446.  
  447.     picCanvas.Line (m_StartX, m_StartY)-(m_CurX, m_CurY), , B
  448.     picCanvas.DrawMode = vbCopyPen
  449.     m_CurX = X
  450.     m_CurY = Y
  451.     
  452.     ' Put the coordinates in proper order.
  453.     If m_CurX < m_StartX Then
  454.         x1 = m_CurX
  455.         x2 = m_StartX
  456.     Else
  457.         x1 = m_StartX
  458.         x2 = m_CurX
  459.     End If
  460.     If x1 = x2 Then x2 = x1 + 1
  461.     If m_CurY < m_StartY Then
  462.         y1 = m_CurY
  463.         y2 = m_StartY
  464.     Else
  465.         y1 = m_StartY
  466.         y2 = m_CurY
  467.     End If
  468.     If y1 = y2 Then y2 = y1 + 1
  469.  
  470.     ' Convert screen coords into drawing coords.
  471.     factor = (m_Xmax - m_Xmin) / picCanvas.ScaleWidth
  472.     m_Xmax = m_Xmin + x2 * factor
  473.     m_Xmin = m_Xmin + x1 * factor
  474.  
  475.     factor = (m_Ymax - m_Ymin) / picCanvas.ScaleHeight
  476.     m_Ymax = m_Ymin + y2 * factor
  477.     m_Ymin = m_Ymin + y1 * factor
  478.  
  479.     Screen.MousePointer = vbHourglass
  480.     DrawFractal
  481.     Screen.MousePointer = vbDefault
  482. End Sub
  483.  
  484.  
  485.  
  486. ' Force Visual Basic to resize the bitmap.
  487. Private Sub picCanvas_Resize()
  488.     picCanvas.Cls
  489. End Sub
  490.  
  491.  
  492. ' Save the picture.
  493. Private Sub mnuFileSaveAs_Click()
  494. Dim file_name As String
  495.  
  496.     ' Allow the user to pick a file.
  497.     On Error Resume Next
  498.  
  499.     dlgFile.DialogTitle = "Save As File"
  500.     dlgFile.Flags = cdlOFNOverwritePrompt + cdlOFNHideReadOnly
  501.     dlgFile.ShowSave
  502.     If Err.Number = cdlCancel Then
  503.         Exit Sub
  504.     ElseIf Err.Number <> 0 Then
  505.         Beep
  506.         MsgBox "Error selecting file.", , vbExclamation
  507.         Exit Sub
  508.     End If
  509.     On Error GoTo 0
  510.  
  511.     file_name = Trim$(dlgFile.FileName)
  512.     dlgFile.InitDir = Left$(file_name, Len(file_name) _
  513.         - Len(dlgFile.FileTitle) - 1)
  514.  
  515.     ' Save the picture.
  516.     SavePicture picCanvas.Image, file_name
  517. End Sub
  518.  
  519. ' Draw the initial Mandelbrot set.
  520. Private Sub Form_Load()
  521. Dim i As Integer
  522.  
  523.     Me.Show
  524.     DoEvents
  525.  
  526.     MaxMandelbrotIterations = 64
  527.     MaxJuliaIterations = 16
  528.  
  529.     ' Create some default colors.
  530.     ResetColors
  531.     AddColor frmConfig.picColor(40).BackColor
  532.     For i = 17 To 23
  533.         AddColor frmConfig.picColor(i).BackColor
  534.     Next i
  535.     Unload frmConfig
  536.  
  537.     dlgFile.Filter = "Bitmap Files (*.bmp)|*.bmp|" & _
  538.         "All Files (*.*)|*.*"
  539.     dlgFile.InitDir = App.Path
  540.     dlgFile.CancelError = True
  541.  
  542.     ' Display the first Mandelbrot set.
  543.     mnuScaleFull_Click
  544. End Sub
  545.  
  546. Private Sub Form_Resize()
  547.     picCanvas.Move 0, 0, ScaleWidth, ScaleHeight
  548. End Sub
  549.  
  550.  
  551.  
  552. ' Let the user set program options.
  553. Private Sub mnuOptOptions_Click()
  554.     frmConfig.Initialize Me
  555.     frmConfig.Show vbModal
  556. End Sub
  557.  
  558. ' Zoom out to full scale.
  559. Private Sub mnuScaleFull_Click()
  560.     m_Xmin = MIN_X
  561.     m_Xmax = MAX_X
  562.     m_Ymin = MIN_Y
  563.     m_Ymax = MAX_Y
  564.  
  565.     Screen.MousePointer = vbHourglass
  566.     DrawFractal
  567.     Screen.MousePointer = vbDefault
  568. End Sub
  569.  
  570. ' Make a series of images.
  571. Private Sub MakeMovie(file_name As String)
  572. Dim num_frames As Integer
  573. Dim frame As Integer
  574. Dim fraction As Single  ' Amount to reduce image.
  575. Dim xmid As Single      ' Center of image.
  576. Dim ymid As Single
  577. Dim wid1 As Single      ' Starting dimensions.
  578. Dim hgt1 As Single
  579. Dim wid2 As Single      ' Finishing dimensions.
  580. Dim hgt2 As Single
  581. Dim wid As Single       ' Current dimensions.
  582. Dim hgt As Single
  583.  
  584. Dim start_time As Single
  585. Dim stop_time As Single
  586. Dim max_time As Single
  587. Dim min_time As Single
  588.  
  589. Dim txt As String
  590. Dim value As Integer
  591.  
  592.     ' See how may frames the user wants.
  593.     txt = InputBox("Number of frames:", _
  594.         "Frames", "20")
  595.     If txt = "" Then Exit Sub
  596.     If IsNumeric(txt) Then num_frames = CInt(txt)
  597.     If num_frames < 1 Then num_frames = 20
  598.  
  599.     Screen.MousePointer = vbHourglass
  600.     max_time = 0
  601.     min_time = 100000
  602.  
  603.     ' Set the center of focus and dimensions.
  604.     xmid = (m_Xmin + m_Xmax) / 2
  605.     ymid = (m_Ymin + m_Ymax) / 2
  606.     wid1 = MAX_X - MIN_X
  607.     wid2 = m_Xmax - m_Xmin
  608.  
  609.     ' Compute start and finish heights.
  610.     hgt1 = wid1 * picCanvas.ScaleHeight / picCanvas.ScaleWidth
  611.     hgt2 = wid2 * picCanvas.ScaleHeight / picCanvas.ScaleWidth
  612.  
  613.     ' Compute the amount to reduce the image for
  614.     ' each frame.
  615.     fraction = Exp(Log(wid2 / wid1) / (num_frames - 1))
  616.  
  617.     ' Start cranking out frames.
  618.     wid = wid1
  619.     hgt = hgt1
  620.     For frame = 0 To num_frames - 1
  621.         Caption = "Julia " & Str$(frame) & _
  622.             "/" & Format$(num_frames - 1)
  623.         m_Xmin = xmid - wid / 2
  624.         m_Xmax = xmid + wid / 2
  625.         m_Ymin = ymid - hgt / 2
  626.         m_Ymax = ymid + hgt / 2
  627.  
  628.         start_time = Timer
  629.         DrawFractal
  630.         stop_time = Timer
  631.  
  632.         If min_time > stop_time - start_time Then min_time = stop_time - start_time
  633.         If max_time < stop_time - start_time Then max_time = stop_time - start_time
  634.  
  635.         SavePicture picCanvas.Image, _
  636.             file_name & Format$(frame) & ".bmp"
  637.         Beep
  638.         DoEvents
  639.  
  640.         wid = wid * fraction
  641.         hgt = hgt * fraction
  642.     Next frame
  643.  
  644.     Screen.MousePointer = vbDefault
  645.  
  646.     MsgBox _
  647.         "Longest:  " & Format$(max_time, "0.00") & _
  648.             " seconds." & vbCrLf & _
  649.         "Shortest: " & Format$(min_time, "0.00") & _
  650.             " seconds." & vbCrLf
  651. End Sub
  652. ' Make a series of images.
  653. Private Sub mnuMovieCreate_Click()
  654. Dim old_file_name As String
  655. Dim file_name As String
  656. Dim pos As Integer
  657.  
  658.     ' Allow the user to pick a file.
  659.     On Error Resume Next
  660.     old_file_name = dlgFile.FileName
  661.     dlgFile.DialogTitle = "Select base file name (no number)"
  662.     dlgFile.Flags = cdlOFNOverwritePrompt + cdlOFNHideReadOnly
  663.  
  664.     pos = InStr(old_file_name, ".")
  665.     If pos > 0 Then old_file_name = Left$(old_file_name, pos - 1)
  666.     dlgFile.FileName = old_file_name
  667.  
  668.     dlgFile.ShowSave
  669.     If Err.Number = cdlCancel Then
  670.         dlgFile.FileName = old_file_name
  671.         Exit Sub
  672.     ElseIf Err.Number <> 0 Then
  673.         dlgFile.FileName = old_file_name
  674.         MsgBox "Error selecting file.", , vbExclamation
  675.         Exit Sub
  676.     End If
  677.     On Error GoTo 0
  678.     
  679.     file_name = Trim$(dlgFile.FileName)
  680.     dlgFile.FileName = old_file_name
  681.     dlgFile.InitDir = Left$(file_name, Len(file_name) _
  682.         - Len(dlgFile.FileTitle) - 1)
  683.  
  684.     ' Trim off the extension if any.
  685.     pos = InStr(file_name, ".")
  686.     If pos > 0 Then file_name = Left$(file_name, pos - 1)
  687.     
  688.     ' Add a trailing underscore if needed.
  689.     If Right$(file_name, 1) <> "_" Then _
  690.         file_name = file_name & "_"
  691.     
  692.     ' Make the movie.
  693.     MakeMovie file_name
  694. End Sub
  695. ' Increase the area shown by a factor of Index.
  696. Private Sub mnuScale_Click(Index As Integer)
  697. Dim size As Single
  698. Dim mid As Single
  699.  
  700.     size = Index * (m_Xmax - m_Xmin)
  701.     If size > 3.2 Then
  702.         mnuScaleFull_Click
  703.         Exit Sub
  704.     End If
  705.     mid = (m_Xmin + m_Xmax) / 2
  706.     m_Xmin = mid - size / 2
  707.     m_Xmax = mid + size / 2
  708.     
  709.     size = Index * (m_Ymax - m_Ymin)
  710.     If size > 2.4 Then
  711.         mnuScaleFull_Click
  712.         Exit Sub
  713.     End If
  714.     mid = (m_Ymin + m_Ymax) / 2
  715.     m_Ymin = mid - size / 2
  716.     m_Ymax = mid + size / 2
  717.     
  718.     Screen.MousePointer = vbHourglass
  719.     DrawFractal
  720.     Screen.MousePointer = vbDefault
  721. End Sub
  722.  
  723.